package com.cqupt.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cqupt.mapper.TopologyMapper;
import com.cqupt.pojo.ResponseMessage;
import com.cqupt.service.HostMapService;
import com.cqupt.utils.APIUtils;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.SocketUtils;

import javax.naming.Name;
import java.util.*;

/**
 * @auther axb
 * @date 2021/3/17 - 14:28
 * 拓扑图的增删改查
 */
@Service
public class HostMapServiceImpl implements HostMapService {

    @Autowired
    TopologyMapper topologyMapper;

    /**
     * 封装默认颜色数据，用于拓扑图元素颜色设置（RGB-十六进制）
     */
    private Map<String, String> colorMap = new HashMap<String, String>(){{
        put("10,204,80", "0ACC50");
    }};

    /**
     * 获取所有的拓扑图的名字
     * @return
     */
    public List<Map<String, Object>> getNamesOfMap() {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.get");
            put("id", 1);
            put("auth", token);
            /**
             * 返回结果过滤：
             * name拓扑图名称
             * sysmapid拓扑图id
             */
            put("params", new HashMap<String, Object>() {{
                List<String> output = new ArrayList<>();
                output.add("name");
                output.add("sysmapid");
                put("output", output);
            }});
        }};

        // 请求发送
        Map<String, Object> result = APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
        return (List<Map<String, Object>>)result.get("result");
    }

    /**
     * 获取所有的拓扑图
     * @return Map<String, Object> results
     */
    public List<Map<String, Object>> getAllMap() {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>() {{
                /**
                 * 筛选拓扑图基本信息：
                 * name名称
                 * sysmapid拓扑图id
                 * width拓扑图宽
                 * height拓扑图高
                 * grid_show是否显示网格
                 */
                List<String> output = new ArrayList<>();
                output.add("name");
                output.add("sysmapid");
                output.add("width");
                output.add("height");
                output.add("grid_show");

                /**
                 * 元素基本信息：
                 * selementid 元素id
                 * label 元素名称
                 * x 元素横坐标
                 * y 元素纵坐标
                 * width 元素宽
                 * height 元素高
                 */
                List<String> selectSelements = new ArrayList<>();
                // 图片对应的hostis
                selectSelements.add("elements");
                // 主机图片显示的类别（server，host）
                selectSelements.add("iconid_off");
                // 图片的id（用于link的表示）
                selectSelements.add("selementid");
                selectSelements.add("label");
                selectSelements.add("x");
                selectSelements.add("y");
                selectSelements.add("width");
                selectSelements.add("height");

                /**
                 * 连线基本信息：
                 * linkid 连线id
                 * color 线颜色
                 * selementid1 线端点1
                 * selementid2 线端点2
                 */
                List<String> selectLinks = new ArrayList<>();
                selectLinks.add("linkid");
                selectLinks.add("color");
                selectLinks.add("selementid1");
                selectLinks.add("selementid2");

                put("output", output);
                put("selectSelements", selectSelements);
                put("selectLinks", selectLinks);
            }});
        }};

        // 请求发送
        Map<String, Object> response = APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
        List<Map<String, Object>> result = (List<Map<String, Object>>) response.get("result");

        // 返回结果封装，依据使用图片类型确定元素类型
        for (Map<String, Object> map : result) {
            List<Map<String, Object>> selements = (List<Map<String, Object>>) map.get("selements");
            for (Map<String, Object> item : selements) {
                int iconid_off = Integer.parseInt((String) item.get("iconid_off"));
                switch (iconid_off) {
                    case 5:
                        item.put("elementtype", "3");
                        break;
                    case 151:
                        item.put("elementtype", "1");
                        break;
                    case 156:
                        item.put("elementtype", "2");
                        break;
                    default:
                        item.put("elementtype", "3");
                }
            }
        }
        return result;
    }

    /**
     * 根据拓扑图名字获取拓扑图中的内容(查找所有使用名称进行过滤)
     * @param name String name
     * @return Map<String, Object> results
     */
    public List<Map<String, Object>> getMapByName(final String name) {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>() {{
                /**
                 * 筛选拓扑图基本信息：
                 * name名称
                 * sysmapid拓扑图id
                 * width拓扑图宽
                 * height拓扑图高
                 * grid_show是否显示网格
                 */
                List<String> output = new ArrayList<>();
                output.add("name");
                output.add("sysmapid");
                output.add("width");
                output.add("height");
                output.add("grid_show");

                /**
                 * 元素基本信息：
                 * selementid 元素id
                 * label 元素名称
                 * x 元素横坐标
                 * y 元素纵坐标
                 * width 元素宽
                 * height 元素高
                 */
                List<String> selectSelements = new ArrayList<>();
                // 图片对应的hostis
                selectSelements.add("elements");
                // 主机图片显示的类别（server，host）
                selectSelements.add("iconid_off");
                // 图片的id（用于link的表示）
                selectSelements.add("selementid");
                selectSelements.add("label");
                selectSelements.add("x");
                selectSelements.add("y");
                selectSelements.add("width");
                selectSelements.add("height");

                /**
                 * 连线基本信息：
                 * linkid 连线id
                 * color 线颜色
                 * selementid1 线端点1
                 * selementid2 线端点2
                 */
                List<String> selectLinks = new ArrayList<>();
                selectLinks.add("linkid");
                selectLinks.add("color");
                selectLinks.add("selementid1");
                selectLinks.add("selementid2");

                put("output", output);
                put("selectSelements", selectSelements);
                put("selectLinks", selectLinks);
                put("filter", new HashMap<String, Object>() {{
                    put("name", name);
                }});
            }});
        }};

        // 请求发送并返回结果
        Map<String, Object> result = APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
        return (List<Map<String, Object>>)result.get("result");
    }

    /**
     * 根据拓扑图id获取拓扑图中的内容
     * @param sysmapid(String)
     * @return Map<String, Object> results
     */
    @Override
    public List<Map<String, Object>> getMapBySysmapid(final String sysmapid) {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>() {{
                List<String> output = new ArrayList<>();
                /**
                 * 筛选拓扑图基本信息：
                 * name名称
                 * sysmapid拓扑图id
                 * width拓扑图宽
                 * height拓扑图高
                 * grid_show是否显示网格
                 */
                output.add("name");
                output.add("sysmapid");
                output.add("width");
                output.add("height");
                output.add("grid_show");

                /**
                 * 元素基本信息：
                 * selementid 元素id
                 * label 元素名称
                 * x 元素横坐标
                 * y 元素纵坐标
                 * width 元素宽
                 * height 元素高
                 */
                List<String> selectSelements = new ArrayList<>();
                selectSelements.add("elements");// 图片对应的hostis
                selectSelements.add("iconid_off");// 主机图片显示的类别（server，host）
                selectSelements.add("selementid");// 图片的id（用于link的表示）
                selectSelements.add("label");
                selectSelements.add("x");
                selectSelements.add("y");
                selectSelements.add("width");
                selectSelements.add("height");

                /**
                 * 连线基本信息：
                 * linkid 连线id
                 * color 线颜色
                 * selementid1 线端点1
                 * selementid2 线端点2
                 */
                List<String> selectLinks = new ArrayList<>();
                selectLinks.add("linkid");
                selectLinks.add("color");
                selectLinks.add("selementid1");
                selectLinks.add("selementid2");

                put("output", output);
                put("selectSelements", selectSelements);
                put("selectLinks", selectLinks);
                put("sysmapids", sysmapid);
            }});
        }};

        // 请求发送并返回结果
        Map<String, Object> result = APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
        return (List<Map<String, Object>>)result.get("result");
    }

    /**
     * 删除拓扑图
     * @param sysmapid 拓扑图id
     * @return
     */
    public Map<String, Object> deleteMapById(String sysmapid) {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.delete");
            put("auth", token);
            put("id", 1);
            put("params", new ArrayList<String>(){{
                add(sysmapid);
            }});
        }};

        // 请求发送并返回结果
        return APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
    }

    /**
     * 创建一个拓扑图
     * @param params
     * @return
     */
    @Override
    public Map<String, Object> createMap(Map<String,Object> params) {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.create");
            put("auth", token);
            put("id", 1);
            put("params", params);
        }};

        // 请求发送并返回结果
        Map<String, Object> result = APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
        return result;
    }

    /**
     * 更新拓扑图
     * @param params
     * @return
     */
    public Map<String, Object> updateMap(Map<String,Object> params) {
        // 获取令牌
        String token = APIUtils.getToken();

        // 请求参数封装
        Map<String, Object> handleParams = handleTopoParams(params);
        Map<String, Object> paramMap = new HashMap<String, Object>() {{
            put("jsonrpc", "2.0");
            put("method", "map.update");
            put("auth", token);
            put("id", 1);
            put("params", handleParams);
        }};

        // 请求发送并返回结果
        return APIUtils.sendRequest(JSON.toJSONString(paramMap, SerializerFeature.WriteMapNullValue));
    }

    /**
     * 处理拓扑图更新创建所需的参数(注意更新需加入参数sysmapid)
     *  1. 对必要的参数进行判空,封装
     * @param params 以下列出创建一个拓扑图目前所需要的参数,包括以下或不仅包括以下
     * {
     *     "name":"",                     (拓扑图名称-must)
     *     "witdh":"",                    (拓扑图宽-must)
     *     "height":"",                   (拓扑图高-must)
     *     "grid_show":"",                (是否显示网格-maybe null)
     *     "selements":[                  (拓扑图元素列表,主要为物理机,maybe null"若为null则创建空拓扑图")
     *         {
     *             "elements":[
     *                 {"hostid": "1037"} (若selements不为null,则此参数为必须)
     *             ],
     *             "elementtype":"",      (拓扑图元素类型-0-host,4-image...;若selements不为null,则此参数为必须)
     *             "selementid":"1",      (String-拓扑图元素的id(貌似任意,但必须保证唯一,用于连线使用),若selements不为null,则此参数为必须)
     *             "iconid_off":"",       (在默认状态下显示元素的图像的ID。若selements不为null,则此参数为必须)
     *             "label":"",            (拓扑图元素名称,maybe null)
     *             "x":"",                (Integer-拓扑图元素横坐标,maybe null(默认0))
     *             "y":"",                (Integer-拓扑图元素纵坐标,maybe null(默认0))
     *             "width":"",            (拓扑图元素宽,maybe null(默认200))
     *             "height":""            (拓扑图元素高,maybe null(默认200))
     *         },
     *         {
     *
     *         }
     *     ],
     *     "links":[                      (拓扑图连线列表,maybe null"若为null则创建无连线的拓扑图")
     *         {
     *             "selementid1": "1",    (连线一端;若links不为null,则此参数为必须)
     *             "selementid2": "2",    (连线另一端;若links不为null,则此参数为必须)
     *             "color": "1"           (颜色,maybe null)
     *         },
     *         {
     *
     *         }
     *     ]
     * }
     * @return 参数列表
     */
    public Map<String, Object> handleTopoParams(Map<String, Object> params) {
        Map<String, Object> handleParams = new HashMap<>();

        // 元素
        List<Map<String, Object>> selements = new ArrayList<Map<String, Object>>();
        if (params.get("selements") != null) {
            for (Map<String, Object> item : (List<Map<String, Object>>) params.get("selements")) {
                selements.add(new HashMap<String, Object>() {{
                    /**
                     * 拓扑图元素基本信息:
                     * selementid 元素id
                     * label 元素名称
                     * x 元素横坐标
                     * y 元素纵坐标
                     * width 元素宽
                     * height 元素高
                     */
                    put("label", item.get("label"));
                    put("iconid_off", item.get("iconid_off"));
                    put("x", item.get("x"));
                    put("y", item.get("y"));
                    put("elements", item.get("elements"));
                    put("selementid", item.get("selementid"));
                    put("height", item.get("height"));
                    put("width", item.get("width"));

                    /**
                     * 拓扑图元素类型未指定,则默认为图像
                     * 0 host,
                     * 2 trigger,
                     * 4 image
                     */
                    if (item.get("elementtype") == null) {
                        put("elementtype", 4);
                        put("elements", null);
                    } else {
                        int elementtype = Integer.parseInt(item.get("elementtype").toString());
                        if (((Map) ((List) item.get("elements")).get(0)).get("hostid") == "" || ((Map) ((List) item.get("elements")).get(0)).get("hostid") == null) {//拓扑图主机id未指定,也默认为图像
                            put("elementtype", 4);
                            put("elements", null);
                        } else {
                            if (elementtype != 4) {
                                put("elementtype", 0);
                            }
                        }
                    }
                }});
            }
            handleParams.put("selements", selements);
        }

        // 连线
        if (params.get("links") != null) {
            List<Map<String, String>> links = (List<Map<String, String>>) params.get("links");
            List<Map<String, String>> handleLinks = new ArrayList<>();
            for (Map<String, String> item : links) {
                handleLinks.add(new HashMap<String, String>() {{
                    /**
                     * selementid1 连线端点1
                     * selementid2 连线端点2
                     * color 连线颜色
                     */
                    put("selementid1", item.get("selementid1"));
                    put("selementid2", item.get("selementid2"));
                    put("color", colorMap.get(item.get("color")));
                }});
            }
            handleParams.put("links", handleLinks);
        }

        // 拓扑图id（此参数仅拓扑图更新时需要）
        if (params.get("sysmapid") != null) {
            handleParams.put("sysmapid", params.get("sysmapid"));
        }

        // 网格
        if (params.get("grid_show") != null) {
            handleParams.put("grid_show", params.get("grid_show"));
        }

        /**
         * width 拓扑图长
         * height 拓扑图宽
         * name 拓扑图名称
         */
        handleParams.put("width", params.get("width"));
        handleParams.put("height", params.get("height"));
        handleParams.put("name", params.get("name"));

        return handleParams;
    }

    /**
     * 注意：关于机房机柜的操作目前并未涉及，仅保留了接口
     **/

    /**
     * 创建机房
     * @param params
     * @return
     */
    @Override
    public int createEngineRoom(Map<String, Object> params) {
        // 检测机房名以及机房号是否已经存在

        return topologyMapper.insertEngineRoom(params);
    }

    /**
     * 更新机房相关信息
     * @param params
     * @return
     */
    @Override
    public int updateEngineRoom(Map<String, Object> params) {
        // 检查其所更新的机房名是否与已存在的冲突

        return topologyMapper.updateEngineRoom(params);
    }

    /**
     * 删除机房
     * @param params
     * @return
     */
    @Override
    public int deleteEngineRoom(ArrayList<String> params) {
        return topologyMapper.deleteEngineRoom(params);
    }

    /**
     * 查询机房
     * @param params
     * @return
     */
    @Override
    public List<Map<String, Object>> getEngineRoom(Map<String, Object> params) {
        return topologyMapper.selectAllEngineRooms(null);
    }

    /**
     * 创建机柜
     * @param params
     * @return
     */
    @Override
    public int createCabinet(Map<String, Object> params) {
        return topologyMapper.insertCabinet(params);
    }

    /**
     * 更新机柜信息
     * @param params
     * @return
     */
    @Override
    public Map<String, Object> updateCabinet(Map<String, Object> params) {
        return null;
    }

    /**
     * 根据机柜的serial_number，删除机柜
     * @param params
     * @return
     */
    @Override
    public int deleteCabinet(ArrayList<String> params) {
        return topologyMapper.deleteCabinetBySerial_number(params);
    }

    /**
     * 根据机房编号查询其下所有机柜，或根据机柜编号查询
     * @param params
     * @return
     */
    @Override
    public List<Map<String, Object>> getCabinet(Map<String, Object> params) {
        return topologyMapper.selectCabinets(params);
    }
}